﻿using System;
using System.Xml;
using System.Xml.Linq;
using System.Data.Services.Client;
using System.Linq;
using System.Drawing.Imaging;
using System.Collections.Generic;

namespace WASM.WebSite.Logic
{
	public static class TableHelper
	{
		private static XNamespace _atomNamespace = "http://www.w3.org/2005/Atom";
		private static XNamespace _astoriaDataNamespace = "http://schemas.microsoft.com/ado/2007/08/dataservices";
		private static XNamespace _astoriaMetadataNamespace = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";

		public static void OnReadingEntity(object sender, ReadingWritingEntityEventArgs args)
		{
			TableGenericEntity entity = args.Entity as TableGenericEntity;
			if (entity == null)
			{
				return;
			}

			// read each property, type and value in the payload   
			var properties = args.Entity.GetType().GetProperties();
			var q = from p in args.Data.Element(_atomNamespace + "content")
															.Element(_astoriaMetadataNamespace + "properties")
															.Elements()
							where properties.All(pp => pp.Name != p.Name.LocalName)
							select new
							{
								Name = p.Name.LocalName,
								IsNull = string.Equals("true", p.Attribute(_astoriaMetadataNamespace + "null") == null ? null : p.Attribute(_astoriaMetadataNamespace + "null").Value, StringComparison.OrdinalIgnoreCase),
								TypeName = p.Attribute(_astoriaMetadataNamespace + "type") == null ? null : p.Attribute(_astoriaMetadataNamespace + "type").Value,
								p.Value
							};

			foreach (var dp in q)
			{
				entity[dp.Name] = GetTypedEdmValue(dp.TypeName, dp.Value, dp.IsNull);
			}
		}

		private static object GetTypedEdmValue(string type, string value, bool isnull)
		{
			if (isnull) return null;

			if (string.IsNullOrEmpty(type)) return value;

			switch (type)
			{
				case "Edm.String": return value;
				case "Edm.Byte": return Convert.ChangeType(value, typeof(byte));
				case "Edm.SByte": return Convert.ChangeType(value, typeof(sbyte));
				case "Edm.Int16": return Convert.ChangeType(value, typeof(short));
				case "Edm.Int32": return Convert.ChangeType(value, typeof(int));
				case "Edm.Int64": return Convert.ChangeType(value, typeof(long));
				case "Edm.Double": return Convert.ChangeType(value, typeof(double));
				case "Edm.Single": return Convert.ChangeType(value, typeof(float));
				case "Edm.Boolean": return Convert.ChangeType(value, typeof(bool));
				case "Edm.Decimal": return Convert.ChangeType(value, typeof(decimal));
				case "Edm.DateTime": return XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.RoundtripKind);
				case "Edm.Binary": return Convert.FromBase64String(value);
				case "Edm.Guid": return new Guid(value);

				default: throw new NotSupportedException("Not supported type " + type);
			}
		}

		public static void OnWritingEntity(object sender, ReadingWritingEntityEventArgs e)
		{
				XElement entry = e.Data;

				string entryTS = entry.ToString();
				string entryV = entry.Value;

				XElement content = entry.Element(XName.Get("content", _atomNamespace.NamespaceName));

				string contentTS = content.ToString();
				string contentV = content.Value;

				XElement properties = content.Element(XName.Get("properties", _astoriaMetadataNamespace.NamespaceName));

				string propertiesTS = properties.ToString();
				string propertiesV = properties.Value;

				foreach (TableGenericProperty kvp in ((TableGenericEntity)e.Entity).Properties)
				{
					string value;
					if (kvp.Value.GetType() == typeof(System.String[]))
						value = ((System.String[])kvp.Value)[0];
					else
						value = kvp.Value.ToString();

					properties.Add(new XElement(XName.Get(kvp.Key, _astoriaDataNamespace.NamespaceName), value));
				}
			}
	}
}
